#pragma once

#include "Thread.hpp"
#include "LockGuard.hpp"
#include "log.hpp"
#include <mutex>
#include <vector>
#include <queue>

using namespace mythread;
template <class T>
class ThreadPool;

template <class T>
class ThreadData
{
public:
    ThreadData(ThreadPool<T> *threadpool, const std::string &name) : _threadpool(threadpool)
    {
    }

public:
    ThreadPool<T> *_threadpool;
    std::string _name;
};

template <class T>
class ThreadPool
{
    const static int g_size = 10;

private:
    static void *handlerTask(void *args)
    {
        // ThreadPool<T> *pthreadpool = static_cast<ThreadPool<T> *>(args);
        ThreadData<T> *td = static_cast<ThreadData<T> *>(args);

        while (true)
        {
            T t;
            {
                LockGuard lockguard(td->_threadpool->mutex());
                while (td->_threadpool->isQueueEmpty())
                    td->_threadpool->threadWait();
                td->_threadpool->pop(&t); // pop的本质就是将任务从共享队列中拿到线程自己栈结构中
            }

            t();
        }

        delete td;
        return nullptr;
    }
    ThreadPool(const int size = g_size) : _size(size)
    {
        
        _threads.reserve(_size);

        for (int i = 0; i < _size; ++i)
            // _threads[i] = new Thread();
            _threads.push_back(new Thread());

        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }
    void operator=(const ThreadPool &) = delete;
    ThreadPool(const ThreadPool &) = delete;

public:
    // void lockQueue() { pthread_mutex_lock(&_mutex); }
    // void unlockQueue() { pthread_mutex_unlock(&_mutex); }
    bool isQueueEmpty() const { return _task_queue.empty(); }
    void threadWait() { pthread_cond_wait(&_cond, &_mutex); }
    void pop(T *t)
    {
        *t = _task_queue.front();
        _task_queue.pop();
    }
    pthread_mutex_t* mutex()
    {
        return &_mutex;
    }
public:
    void push(const T &in)
    {
        LockGuard lockguard(&_mutex);
        _task_queue.push(in);
        pthread_cond_signal(&_cond);
    }
    void run()
    {
        for (const auto &t : _threads)
        {
            ThreadData<T> *td = new ThreadData<T>(this, t->thread_name());
            t->start(handlerTask, td);
            // std::cout << t->thread_name() << " run ..." << std::endl;
            logMessage(NORMAL, "%s run ...", t->thread_name().c_str());
        }
    }

    // void join()
    // {
    //     for (const auto &t : _threads)
    //     {
    //         t->join();
    //     }
    // }

    // 获得单例
    static ThreadPool<T> *getSingleInstance()
    {
        if (tp == nullptr)// 提高并发度
        {
            single_lock.lock();// 保证单例安全
            if (tp == nullptr)
            {
                tp = new ThreadPool<T>();
            }
            single_lock.unlock();
        }

        return tp;
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for (const auto &t : _threads)
            delete t;
    }

private:
    int _size;                   // 线程池中线程个数
    std::vector<Thread *> _threads; // 队列集
    std::queue<T> _task_queue;      // 任务队列
    pthread_mutex_t _mutex;         // 互斥锁
    pthread_cond_t _cond;           // 条件变量

    static ThreadPool<T> *tp;      //
    static std::mutex single_lock; //
};

template <class T>
ThreadPool<T> *ThreadPool<T>::tp = nullptr; // 初始化tp
template <class T>
std::mutex ThreadPool<T>::single_lock; // 初始化单例锁
